package io.demo.message.util;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import io.demo.message.domain.Address;
import io.demo.message.domain.AddressType;
import io.demo.message.domain.AdminLevel;
import io.demo.message.domain.Area;
import io.demo.message.domain.City;
import io.demo.message.domain.Country;
import io.demo.message.domain.Customer;
import io.demo.message.domain.Ethnic;
import io.demo.message.domain.GenderType;
import io.demo.message.domain.IntegerValue;
import io.demo.message.domain.SkinColor;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import org.apache.commons.lang3.RandomUtils;

public class TestingModels {

  private static final Map
      <Class<? extends Serializable>, Supplier<? extends Serializable>> MODEL_GENERATORS;

  private static final Map
      <Class<? extends IntegerValue>, List<? extends IntegerValue>> INTEGER_VALUES_GENERATOR;

  private TestingModels() {
  }

  public static Area area() {
    return randomDomainObject(Area.class);
  }

  public static City city() {
    return randomDomainObject(City.class);
  }

  public static Country country() {
    return randomDomainObject(Country.class);
  }

  public static Address address() {
    return randomDomainObject(Address.class);
  }

  public static Ethnic ethnic() {
    return randomDomainObject(Ethnic.class);
  }

  public static Customer customer() {
    return randomDomainObject(Customer.class);
  }

  public static AddressType addressType() {
    return randomDomainEnum(AddressType.class);
  }

  public static SkinColor skinColor() {
    return randomDomainEnum(SkinColor.class);
  }

  public static GenderType genderType() {
    return randomDomainEnum(GenderType.class);
  }

  public static AdminLevel adminLevel() {
    return randomDomainEnum(AdminLevel.class);
  }

  public static <T extends Serializable> T randomDomainObject(Class<T> cc) {
    return cc.cast(MODEL_GENERATORS.get(cc).get());
  }

  public static <T extends IntegerValue> T randomDomainEnum(Class<T> cc) {
    @SuppressWarnings("unchecked")
    List<T> list = (List<T>) INTEGER_VALUES_GENERATOR.get(cc);
    return randomIndex(list);
  }

  private static <T extends IntegerValue> T randomIndex(List<T> list) {
    return list.get(RandomUtils.nextInt(0, list.size()));
  }

  static {

    INTEGER_VALUES_GENERATOR = new ImmutableMap
        .Builder<Class<? extends IntegerValue>, List<? extends IntegerValue>>()
        .put(AddressType.class, ImmutableList.copyOf(AddressType.values()))
        .put(SkinColor.class, ImmutableList.copyOf(SkinColor.values()))
        .put(GenderType.class, ImmutableList.copyOf(GenderType.values()))
        .put(AdminLevel.class, ImmutableList.copyOf(AdminLevel.values()))
        .build();

    MODEL_GENERATORS = new ImmutableMap
        .Builder<Class<? extends Serializable>, Supplier<? extends Serializable>>()
        .put(Area.class, new RandomAreaSupplier())
        .put(City.class, new RandomCitySupplier())
        .put(Country.class, new RandomCountrySupplier())
        .put(Address.class, new RandomAddressSupplier())
        .put(Ethnic.class, new RandomEthnicSupplier())
        .put(Customer.class, new RandomCustomerSupplier())
        .build();
  }

}
